#include "port.h"

#include "test.h"

class NodeA : public Node
{
public:
    NodeA(JObject *parent = nullptr) : Node(parent),
        buf_in(new PortIn<int>(this)),
        buf_out(new PortOut<int>(this))
    {
    }

    void task_show1()
    {
        buf_out->put(1);
    }

    void task_show2()
    {
        buf_out->put(1);
    }

    void task_show3()
    {
        buf_out->put(1);
    }

    void task_d()
    {
        if(!buf_in->is_empty())
            buf_in->get();
        printf("A: %d\n", buf_in->size());
    }

    NodeTaskList tasks() const override
    {
        NodeTaskList list;
        list.append(static_cast<NodeTask>(&NodeA::task_show1));
        list.append(static_cast<NodeTask>(&NodeA::task_show2));
        list.append(static_cast<NodeTask>(&NodeA::task_show3));
        list.append(static_cast<NodeTask>(&NodeA::task_d));
        return list;
    }

    PortIn<int> *buf_in;
    PortOut<int> *buf_out;
};

class NodeB : public Node
{
public:
    NodeB(JObject *parent = nullptr) : Node(parent),
        buf_in(new PortIn<int>(this)),
        buf_out(new PortOut<int>(this))
    {}

    void task_d()
    {
        if(!buf_in->is_empty())
            buf_in->get();
        printf("B: %d\n", buf_in->size());
    }

    void task_show1()
    {
        buf_out->put(2);
    }

    void task_show2()
    {
        buf_out->put(2);
    }

    NodeTaskList tasks() const override
    {
        NodeTaskList list;
        list.append(static_cast<NodeTask>(&NodeB::task_show1));
        list.append(static_cast<NodeTask>(&NodeB::task_show2));
        list.append(static_cast<NodeTask>(&NodeB::task_d));
        return list;
    }

    PortIn<int> *buf_in;
    PortOut<int> *buf_out;
};

class NodeC : public Node
{
public:
    NodeC(JObject *parent = nullptr) : Node(parent),
        buf_in(new PortIn<int>(this)),
        buf_out(new PortOut<int>(this))
    {}

    void task_show()
    {
        buf_out->put(3);
    }

    void task_d()
    {
        if(!buf_in->is_empty())
            buf_in->get();
        printf("C: %d\n", buf_in->size());
    }

    NodeTaskList tasks() const override
    {
        NodeTaskList list;
        list.append(static_cast<NodeTask>(&NodeC::task_show));
        list.append(static_cast<NodeTask>(&NodeC::task_d));
        return list;
    }

    PortIn<int> *buf_in;
    PortOut<int> *buf_out;
};

TopNode::TopNode() : TopModule()
{
    NodeA *a = new NodeA(this);
    node_add(a);
    NodeB *b = new NodeB(this);
    node_add(b);
    NodeC *c = new NodeC(this);
    node_add(c);

    a->buf_out->connect(b->buf_in);
    b->buf_out->connect(c->buf_in);
    c->buf_out->connect(a->buf_in);
}
